package com.meta.framework.security.filter;

import com.alibaba.fastjson.JSONObject;
import com.meta.framework.act.model.LoginUser;
import com.meta.framework.common.utils.SecurityUtils;
import com.meta.framework.common.utils.StringUtils;
import com.meta.framework.service.TokenService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.UUID;

/**
 * token过滤器 验证token有效性
 *
 * @author ruoyi
 */

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

	private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);

	@Autowired
	private TokenService tokenService;

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws ServletException, IOException {
		try {
			MDC.put("traceId" , UUID.randomUUID().toString().replace("-" , ""));
			logger.info("----filter url :{}-----" , request.getRequestURL());

			LoginUser loginUser = tokenService.getLoginUser(request);
			logger.info("==========login User ==============:{}" , JSONObject.toJSONString(loginUser));
			if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())) {
				tokenService.verifyToken(loginUser);
				UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
				authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
				SecurityContextHolder.getContext().setAuthentication(authenticationToken);
			}
			ContentCachingRequestWrapper req = new ContentCachingRequestWrapper(request);
			ContentCachingResponseWrapper resp = new ContentCachingResponseWrapper(response);

			chain.doFilter(req, resp);
			// Get body
			// 检查文件类型
			String contentType = req.getContentType();
			if (contentType != null && contentType.startsWith("multipart/form-data")) {
				resp.copyBodyToResponse();
				return;
			}
			String json = new String(req.getContentAsByteArray(), StandardCharsets.UTF_8);
			Map<String, String[]> parameterMap = req.getParameterMap();
			byte[] responseBody = resp.getContentAsByteArray();
			String responseValue = responseBody.length < 500 ? new String(responseBody, StandardCharsets.UTF_8) : new String(responseBody, 0, 500 - 1, StandardCharsets.UTF_8);
			logger.info("=====call http api, param map ：{} request body = {}, response body = {}" , JSONObject.toJSONString(parameterMap) ,json, responseValue);
			resp.copyBodyToResponse();
		} finally {
			MDC.remove("traceId");
		}
	}
}
